/* do not edit automatically generated by mc from mcError.  */
/* mcError.mod provides an interface between the string handling modules.

Copyright (C) 2015-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Modula-2; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#   if !defined (TRUE)
#      define TRUE (1==1)
#   endif

#   if !defined (FALSE)
#      define FALSE (1==0)
#   endif

#   include "GStorage.h"
#if defined(__cplusplus)
#   undef NULL
#   define NULL 0
#endif
#define _mcError_H
#define _mcError_C

#   include "GASCII.h"
#   include "GDynamicStrings.h"
#   include "GFIO.h"
#   include "GStrLib.h"
#   include "GFormatStrings.h"
#   include "GStorage.h"
#   include "GM2RTS.h"
#   include "GSYSTEM.h"
#   include "GStdIO.h"
#   include "GnameKey.h"
#   include "GmcLexBuf.h"
#   include "GmcPrintf.h"

#   define Debugging true
#   define DebugTrace false
#   define Xcode true
typedef struct mcError__T2_r mcError__T2;

typedef mcError__T2 *mcError_error;

struct mcError__T2_r {
                       mcError_error parent;
                       mcError_error child;
                       mcError_error next;
                       bool fatal;
                       DynamicStrings_String s;
                       unsigned int token;
                     };

static mcError_error head;
static bool inInternal;

/*
   internalError - displays an internal error message together with the compiler source
                   file and line number.
                   This function is not buffered and is used when the compiler is about
                   to give up.
*/

extern "C" void mcError_internalError (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line);

/*
   writeFormat0 - displays the source module and line together
                  with the encapsulated format string.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat0 (const char *a_, unsigned int _a_high);

/*
   writeFormat1 - displays the source module and line together
                  with the encapsulated format string.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);

/*
   writeFormat2 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high);

/*
   writeFormat3 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat3 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high);

/*
   newError - creates and returns a new error handle.
*/

extern "C" mcError_error mcError_newError (unsigned int atTokenNo);

/*
   newWarning - creates and returns a new error handle suitable for a warning.
                A warning will not stop compilation.
*/

extern "C" mcError_error mcError_newWarning (unsigned int atTokenNo);

/*
   chainError - creates and returns a new error handle, this new error
                is associated with, e, and is chained onto the end of, e.
                If, e, is NIL then the result to NewError is returned.
*/

extern "C" mcError_error mcError_chainError (unsigned int atTokenNo, mcError_error e);
extern "C" void mcError_errorFormat0 (mcError_error e, const char *a_, unsigned int _a_high);
extern "C" void mcError_errorFormat1 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);
extern "C" void mcError_errorFormat2 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high);
extern "C" void mcError_errorFormat3 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high);
extern "C" void mcError_errorString (mcError_error e, DynamicStrings_String str);

/*
   errorStringAt - given an error string, s, it places this
                   string at token position, tok.
                   The string is consumed.
*/

extern "C" void mcError_errorStringAt (DynamicStrings_String s, unsigned int tok);

/*
   errorStringAt2 - given an error string, s, it places this
                    string at token positions, tok1 and tok2, respectively.
                    The string is consumed.
*/

extern "C" void mcError_errorStringAt2 (DynamicStrings_String s, unsigned int tok1, unsigned int tok2);

/*
   errorStringsAt2 - given error strings, s1, and, s2, it places these
                     strings at token positions, tok1 and tok2, respectively.
                     Both strings are consumed.
*/

extern "C" void mcError_errorStringsAt2 (DynamicStrings_String s1, DynamicStrings_String s2, unsigned int tok1, unsigned int tok2);

/*
   warnStringAt - given an error string, s, it places this
                  string at token position, tok.
                  The string is consumed.
*/

extern "C" void mcError_warnStringAt (DynamicStrings_String s, unsigned int tok);

/*
   warnStringAt2 - given an warning string, s, it places this
                   string at token positions, tok1 and tok2, respectively.
                   The string is consumed.
*/

extern "C" void mcError_warnStringAt2 (DynamicStrings_String s, unsigned int tok1, unsigned int tok2);

/*
   warnStringsAt2 - given warning strings, s1, and, s2, it places these
                    strings at token positions, tok1 and tok2, respectively.
                    Both strings are consumed.
*/

extern "C" void mcError_warnStringsAt2 (DynamicStrings_String s1, DynamicStrings_String s2, unsigned int tok1, unsigned int tok2);
extern "C" void mcError_warnFormat0 (const char *a_, unsigned int _a_high);

/*
   warnFormat1 - displays the source module and line together
                 with the encapsulated format string.
                 Used for simple warning messages tied to the current token.
*/

extern "C" void mcError_warnFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);

/*
   flushErrors - switches the output channel to the error channel
                 and then writes out all errors.
*/

extern "C" void mcError_flushErrors (void);

/*
   flushWarnings - switches the output channel to the error channel
                   and then writes out all warnings.
                   If an error is present the compilation is terminated,
                   if warnings only were emitted then compilation will
                   continue.
*/

extern "C" void mcError_flushWarnings (void);

/*
   errorAbort0 - aborts compiling, it flushes all warnings and errors before aborting.
*/

extern "C" void mcError_errorAbort0 (const char *a_, unsigned int _a_high);

/*
   cast - casts a := b
*/

static void cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high);
static bool translateNameToCharStar (char *a, unsigned int _a_high, unsigned int n);

/*
   outString - writes the contents of String to stdout.
               The string, s, is destroyed.
*/

static void outString (DynamicStrings_String file, unsigned int line, unsigned int col, DynamicStrings_String s);
static DynamicStrings_String doFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);

/*
   doFormat2 -
*/

static DynamicStrings_String doFormat2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high);

/*
   writeFormat2 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

static DynamicStrings_String doFormat3 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high);

/*
   init - initializes the error list.
*/

static void init (void);

/*
   checkIncludes - generates a sequence of error messages which determine the relevant
                   included file and line number.
                   For example:

                   gcc a.c
                   In file included from b.h:1,
                                    from a.c:1:
                   c.h:1: parse error before `and'

                   where a.c is: #include "b.h"
                         b.h is: #include "c.h"
                         c.h is: and this and that

                   we attempt to follow the error messages that gcc issues.
*/

static void checkIncludes (unsigned int token, unsigned int depth);

/*
   flushAll - flushes all errors in list, e.
*/

static bool flushAll (mcError_error e, bool FatalStatus);


/*
   cast - casts a := b
*/

static void cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high)
{
  unsigned int i;
  unsigned char b[_b_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (b, b_, _b_high+1);

  if (_a_high == _b_high)
    {
      for (i=0; i<=_a_high; i++)
        {
          a[i] = b[i];
        }
    }
}

static bool translateNameToCharStar (char *a, unsigned int _a_high, unsigned int n)
{
  unsigned int argno;
  unsigned int i;
  unsigned int h;

  /* 
   translateNameToString - takes a format specification string, a, and
                           if they consist of of %a then this is translated
                           into a String and %a is replaced by %s.
  */
  argno = 1;
  i = 0;
  h = StrLib_StrLen ((const char *) a, _a_high);
  while (i < h)
    {
      if ((a[i] == '%') && ((i+1) < h))
        {
          if ((a[i+1] == 'a') && (argno == n))
            {
              a[i+1] = 's';
              return true;
            }
          argno += 1;
          if (argno > n)
            {
              /* all done  */
              return false;
            }
        }
      i += 1;
    }
  return false;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   outString - writes the contents of String to stdout.
               The string, s, is destroyed.
*/

static void outString (DynamicStrings_String file, unsigned int line, unsigned int col, DynamicStrings_String s)
{
  typedef char *outString__T1;

  DynamicStrings_String leader;
  outString__T1 p;
  outString__T1 q;
  bool space;
  bool newline;

  col += 1;
  if (Xcode)
    {
      leader = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%s:%d:", 6)), (const unsigned char *) &file, (sizeof (file)-1), (const unsigned char *) &line, (sizeof (line)-1));
    }
  else
    {
      leader = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%s:%d:%d:", 9)), (const unsigned char *) &file, (sizeof (file)-1), (const unsigned char *) &line, (sizeof (line)-1), (const unsigned char *) &col, (sizeof (col)-1));
    }
  p = static_cast<outString__T1> (DynamicStrings_string (s));
  newline = true;
  space = false;
  while ((p != NULL) && ((*p) != ASCII_nul))
    {
      if (newline)
        {
          q = static_cast<outString__T1> (DynamicStrings_string (leader));
          while ((q != NULL) && ((*q) != ASCII_nul))
            {
              StdIO_Write ((*q));
              q += 1;
            }
        }
      newline = (*p) == ASCII_nl;
      space = (*p) == ' ';
      if (newline && Xcode)
        {
          mcPrintf_printf1 ((const char *) "(pos: %d)", 9, (const unsigned char *) &col, (sizeof (col)-1));
        }
      StdIO_Write ((*p));
      p += 1;
    }
  if (! newline)
    {
      if (Xcode)
        {
          if (! space)
            {
              StdIO_Write (' ');
            }
          mcPrintf_printf1 ((const char *) "(pos: %d)", 9, (const unsigned char *) &col, (sizeof (col)-1));
        }
      StdIO_Write (ASCII_nl);
    }
  FIO_FlushBuffer (FIO_StdOut);
  if (! Debugging)
    {
      s = DynamicStrings_KillString (s);
      leader = DynamicStrings_KillString (leader);
    }
}

static DynamicStrings_String doFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
{
  DynamicStrings_String s;
  nameKey_Name n;
  char a[_a_high+1];
  unsigned char w[_w_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w, w_, _w_high+1);

  /* 
   DoFormat1 -
  */
  if (translateNameToCharStar ((char *) a, _a_high, 1))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w, _w_high);
      s = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s, (sizeof (s)-1));
    }
  else
    {
      s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w, _w_high);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   doFormat2 -
*/

static DynamicStrings_String doFormat2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high)
{
  nameKey_Name n;
  DynamicStrings_String s;
  DynamicStrings_String s1;
  DynamicStrings_String s2;
  unsigned int b;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);

  b = (unsigned int) 0;
  if (translateNameToCharStar ((char *) a, _a_high, 1))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w1, _w1_high);
      s1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      b |= (1 << (1 ));
    }
  if (translateNameToCharStar ((char *) a, _a_high, 2))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w2, _w2_high);
      s2 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      b |= (1 << (2 ));
    }
  switch (b)
    {
      case (unsigned int) 0:
        s = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high);
        break;

      case (unsigned int) ((1 << (1))):
        s = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) w2, _w2_high);
        break;

      case (unsigned int) ((1 << (2))):
        s = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) &s2, (sizeof (s2)-1));
        break;

      case (unsigned int) ((1 << (1)) | (1 << (2))):
        s = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) &s2, (sizeof (s2)-1));
        break;


      default:
        M2RTS_HALT (-1);
        __builtin_unreachable ();
        break;
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   writeFormat2 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

static DynamicStrings_String doFormat3 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high)
{
  nameKey_Name n;
  DynamicStrings_String s;
  DynamicStrings_String s1;
  DynamicStrings_String s2;
  DynamicStrings_String s3;
  unsigned int b;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];
  unsigned char w3[_w3_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);
  memcpy (w3, w3_, _w3_high+1);

  b = (unsigned int) 0;
  if (translateNameToCharStar ((char *) a, _a_high, 1))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w1, _w1_high);
      s1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      b |= (1 << (1 ));
    }
  if (translateNameToCharStar ((char *) a, _a_high, 2))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w2, _w2_high);
      s2 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      b |= (1 << (2 ));
    }
  if (translateNameToCharStar ((char *) a, _a_high, 3))
    {
      cast ((unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) w3, _w3_high);
      s3 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (nameKey_keyToCharStar (n)));
      b |= (1 << (3 ));
    }
  switch (b)
    {
      case (unsigned int) 0:
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high, (const unsigned char *) w3, _w3_high);
        break;

      case (unsigned int) ((1 << (1))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) w2, _w2_high, (const unsigned char *) w3, _w3_high);
        break;

      case (unsigned int) ((1 << (2))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) &s2, (sizeof (s2)-1), (const unsigned char *) w3, _w3_high);
        break;

      case (unsigned int) ((1 << (1)) | (1 << (2))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) &s2, (sizeof (s2)-1), (const unsigned char *) w3, _w3_high);
        break;

      case (unsigned int) ((1 << (3))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high, (const unsigned char *) &s3, (sizeof (s3)-1));
        break;

      case (unsigned int) ((1 << (1)) | (1 << (3))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) w2, _w2_high, (const unsigned char *) &s3, (sizeof (s3)-1));
        break;

      case (unsigned int) ((1 << (2)) | (1 << (3))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) w1, _w1_high, (const unsigned char *) &s2, (sizeof (s2)-1), (const unsigned char *) &s3, (sizeof (s3)-1));
        break;

      case (unsigned int) ((1 << (1)) | (1 << (2)) | (1 << (3))):
        s = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) &s2, (sizeof (s2)-1), (const unsigned char *) &s3, (sizeof (s3)-1));
        break;


      default:
        M2RTS_HALT (-1);
        __builtin_unreachable ();
        break;
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   init - initializes the error list.
*/

static void init (void)
{
  head = NULL;
  inInternal = false;
}


/*
   checkIncludes - generates a sequence of error messages which determine the relevant
                   included file and line number.
                   For example:

                   gcc a.c
                   In file included from b.h:1,
                                    from a.c:1:
                   c.h:1: parse error before `and'

                   where a.c is: #include "b.h"
                         b.h is: #include "c.h"
                         c.h is: and this and that

                   we attempt to follow the error messages that gcc issues.
*/

static void checkIncludes (unsigned int token, unsigned int depth)
{
  DynamicStrings_String included;
  unsigned int lineno;

  included = mcLexBuf_findFileNameFromToken (token, depth+1);
  if (included != NULL)
    {
      lineno = mcLexBuf_tokenToLineNo (token, depth+1);
      if (depth == 0)
        {
          mcPrintf_printf2 ((const char *) "In file included from %s:%d", 27, (const unsigned char *) &included, (sizeof (included)-1), (const unsigned char *) &lineno, (sizeof (lineno)-1));
        }
      else
        {
          mcPrintf_printf2 ((const char *) "                 from %s:%d", 27, (const unsigned char *) &included, (sizeof (included)-1), (const unsigned char *) &lineno, (sizeof (lineno)-1));
        }
      if ((mcLexBuf_findFileNameFromToken (token, depth+2)) == NULL)
        {
          mcPrintf_printf0 ((const char *) ":\\n", 3);
        }
      else
        {
          mcPrintf_printf0 ((const char *) ",\\n", 3);
        }
      checkIncludes (token, depth+1);
    }
}


/*
   flushAll - flushes all errors in list, e.
*/

static bool flushAll (mcError_error e, bool FatalStatus)
{
  mcError_error f;
  bool written;

  written = false;
  if (e != NULL)
    {
      do {
        if ((FatalStatus == e->fatal) && (e->s != NULL))
          {
            checkIncludes (e->token, 0);
            if (e->fatal)
              {
                e->s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) " error: ", 8), DynamicStrings_Mark (e->s));
              }
            else
              {
                e->s = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) " warning: ", 10), DynamicStrings_Mark (e->s));
              }
            outString (mcLexBuf_findFileNameFromToken (e->token, 0), mcLexBuf_tokenToLineNo (e->token, 0), mcLexBuf_tokenToColumnNo (e->token, 0), e->s);
            if ((e->child != NULL) && (flushAll (e->child, FatalStatus)))
              {}  /* empty.  */
            e->s = static_cast<DynamicStrings_String> (NULL);
            written = true;
          }
        f = e;
        e = e->next;
        if (! Debugging)
          {
            f->s = DynamicStrings_KillString (f->s);
            Storage_DEALLOCATE ((void **) &f, sizeof (mcError__T2));
          }
      } while (! (e == NULL));
    }
  return written;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   internalError - displays an internal error message together with the compiler source
                   file and line number.
                   This function is not buffered and is used when the compiler is about
                   to give up.
*/

extern "C" void mcError_internalError (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line)
{
  char a[_a_high+1];
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (file, file_, _file_high+1);

  M2RTS_ExitOnHalt (1);
  if (! inInternal)
    {
      inInternal = true;
      mcError_flushErrors ();
      outString (mcLexBuf_findFileNameFromToken (mcLexBuf_getTokenNo (), 0), mcLexBuf_tokenToLineNo (mcLexBuf_getTokenNo (), 0), mcLexBuf_tokenToColumnNo (mcLexBuf_getTokenNo (), 0), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "*** fatal error ***", 19)));
    }
  outString (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) file, _file_high)), line, 0, DynamicStrings_ConCat (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "*** internal error *** ", 23)), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high))));
  M2RTS_HALT (-1);
  __builtin_unreachable ();
}


/*
   writeFormat0 - displays the source module and line together
                  with the encapsulated format string.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat0 (const char *a_, unsigned int _a_high)
{
  mcError_error e;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  e = mcError_newError (mcLexBuf_getTokenNo ());
  e->s = FormatStrings_Sprintf0 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)));
}


/*
   writeFormat1 - displays the source module and line together
                  with the encapsulated format string.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
{
  mcError_error e;
  char a[_a_high+1];
  unsigned char w[_w_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w, w_, _w_high+1);

  e = mcError_newError (mcLexBuf_getTokenNo ());
  e->s = doFormat1 ((const char *) a, _a_high, (const unsigned char *) w, _w_high);
}


/*
   writeFormat2 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high)
{
  mcError_error e;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);

  e = mcError_newError (mcLexBuf_getTokenNo ());
  e->s = doFormat2 ((const char *) a, _a_high, (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high);
}


/*
   writeFormat3 - displays the module and line together with the encapsulated
                  format strings.
                  Used for simple error messages tied to the current token.
*/

extern "C" void mcError_writeFormat3 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high)
{
  mcError_error e;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];
  unsigned char w3[_w3_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);
  memcpy (w3, w3_, _w3_high+1);

  e = mcError_newError (mcLexBuf_getTokenNo ());
  e->s = doFormat3 ((const char *) a, _a_high, (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high, (const unsigned char *) w3, _w3_high);
}


/*
   newError - creates and returns a new error handle.
*/

extern "C" mcError_error mcError_newError (unsigned int atTokenNo)
{
  mcError_error e;
  mcError_error f;

  Storage_ALLOCATE ((void **) &e, sizeof (mcError__T2));
  e->s = static_cast<DynamicStrings_String> (NULL);
  e->token = atTokenNo;
  e->next = NULL;
  e->parent = NULL;
  e->child = NULL;
  e->fatal = true;
  if ((head == NULL) || (head->token > atTokenNo))
    {
      e->next = head;
      head = e;
    }
  else
    {
      f = head;
      while ((f->next != NULL) && (f->next->token < atTokenNo))
        {
          f = f->next;
        }
      e->next = f->next;
      f->next = e;
    }
  return e;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   newWarning - creates and returns a new error handle suitable for a warning.
                A warning will not stop compilation.
*/

extern "C" mcError_error mcError_newWarning (unsigned int atTokenNo)
{
  mcError_error e;

  e = mcError_newError (atTokenNo);
  e->fatal = false;
  return e;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   chainError - creates and returns a new error handle, this new error
                is associated with, e, and is chained onto the end of, e.
                If, e, is NIL then the result to NewError is returned.
*/

extern "C" mcError_error mcError_chainError (unsigned int atTokenNo, mcError_error e)
{
  mcError_error f;

  if (e == NULL)
    {
      return mcError_newError (atTokenNo);
    }
  else
    {
      Storage_ALLOCATE ((void **) &f, sizeof (mcError__T2));
      f->s = static_cast<DynamicStrings_String> (NULL);
      f->token = atTokenNo;
      f->next = e->child;
      f->parent = e;
      f->child = NULL;
      f->fatal = e->fatal;
      e->child = f;
    }
  return f;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void mcError_errorFormat0 (mcError_error e, const char *a_, unsigned int _a_high)
{
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  /* 
   errorFormat routines provide a printf capability for the error handle.
  */
  if (e->s == NULL)
    {
      e->s = FormatStrings_Sprintf0 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)));
    }
  else
    {
      e->s = DynamicStrings_ConCat (e->s, DynamicStrings_Mark (FormatStrings_Sprintf0 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)))));
    }
}

extern "C" void mcError_errorFormat1 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
{
  DynamicStrings_String s1;
  char a[_a_high+1];
  unsigned char w[_w_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w, w_, _w_high+1);

  s1 = doFormat1 ((const char *) a, _a_high, (const unsigned char *) w, _w_high);
  if (e->s == NULL)
    {
      e->s = s1;
    }
  else
    {
      e->s = DynamicStrings_ConCat (e->s, DynamicStrings_Mark (s1));
    }
}

extern "C" void mcError_errorFormat2 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high)
{
  DynamicStrings_String s1;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);

  s1 = doFormat2 ((const char *) a, _a_high, (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high);
  if (e->s == NULL)
    {
      e->s = s1;
    }
  else
    {
      e->s = DynamicStrings_ConCat (e->s, DynamicStrings_Mark (s1));
    }
}

extern "C" void mcError_errorFormat3 (mcError_error e, const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high, const unsigned char *w3_, unsigned int _w3_high)
{
  DynamicStrings_String s1;
  char a[_a_high+1];
  unsigned char w1[_w1_high+1];
  unsigned char w2[_w2_high+1];
  unsigned char w3[_w3_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w1, w1_, _w1_high+1);
  memcpy (w2, w2_, _w2_high+1);
  memcpy (w3, w3_, _w3_high+1);

  s1 = doFormat3 ((const char *) a, _a_high, (const unsigned char *) w1, _w1_high, (const unsigned char *) w2, _w2_high, (const unsigned char *) w3, _w3_high);
  if (e->s == NULL)
    {
      e->s = s1;
    }
  else
    {
      e->s = DynamicStrings_ConCat (e->s, DynamicStrings_Mark (s1));
    }
}

extern "C" void mcError_errorString (mcError_error e, DynamicStrings_String str)
{
  e->s = str;
}


/*
   errorStringAt - given an error string, s, it places this
                   string at token position, tok.
                   The string is consumed.
*/

extern "C" void mcError_errorStringAt (DynamicStrings_String s, unsigned int tok)
{
  mcError_error e;

  e = mcError_newError (tok);
  mcError_errorString (e, s);
}


/*
   errorStringAt2 - given an error string, s, it places this
                    string at token positions, tok1 and tok2, respectively.
                    The string is consumed.
*/

extern "C" void mcError_errorStringAt2 (DynamicStrings_String s, unsigned int tok1, unsigned int tok2)
{
  mcError_errorStringsAt2 (s, s, tok1, tok2);
}


/*
   errorStringsAt2 - given error strings, s1, and, s2, it places these
                     strings at token positions, tok1 and tok2, respectively.
                     Both strings are consumed.
*/

extern "C" void mcError_errorStringsAt2 (DynamicStrings_String s1, DynamicStrings_String s2, unsigned int tok1, unsigned int tok2)
{
  mcError_error e;

  if (s1 == s2)
    {
      s2 = DynamicStrings_Dup (s1);
    }
  e = mcError_newError (tok1);
  mcError_errorString (e, s1);
  mcError_errorString (mcError_chainError (tok2, e), s2);
}


/*
   warnStringAt - given an error string, s, it places this
                  string at token position, tok.
                  The string is consumed.
*/

extern "C" void mcError_warnStringAt (DynamicStrings_String s, unsigned int tok)
{
  mcError_error e;

  e = mcError_newWarning (tok);
  mcError_errorString (e, s);
}


/*
   warnStringAt2 - given an warning string, s, it places this
                   string at token positions, tok1 and tok2, respectively.
                   The string is consumed.
*/

extern "C" void mcError_warnStringAt2 (DynamicStrings_String s, unsigned int tok1, unsigned int tok2)
{
  mcError_warnStringsAt2 (s, s, tok1, tok2);
}


/*
   warnStringsAt2 - given warning strings, s1, and, s2, it places these
                    strings at token positions, tok1 and tok2, respectively.
                    Both strings are consumed.
*/

extern "C" void mcError_warnStringsAt2 (DynamicStrings_String s1, DynamicStrings_String s2, unsigned int tok1, unsigned int tok2)
{
  mcError_error e;

  if (s1 == s2)
    {
      s2 = DynamicStrings_Dup (s1);
    }
  e = mcError_newWarning (tok1);
  mcError_errorString (e, s1);
  mcError_errorString (mcError_chainError (tok2, e), s2);
}

extern "C" void mcError_warnFormat0 (const char *a_, unsigned int _a_high)
{
  mcError_error e;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  /* 
   WarnFormat0 - displays the source module and line together
                 with the encapsulated format string.
                 Used for simple warning messages tied to the current token.
  */
  e = mcError_newWarning (mcLexBuf_getTokenNo ());
  e->s = FormatStrings_Sprintf0 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) a, _a_high)));
}


/*
   warnFormat1 - displays the source module and line together
                 with the encapsulated format string.
                 Used for simple warning messages tied to the current token.
*/

extern "C" void mcError_warnFormat1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
{
  mcError_error e;
  char a[_a_high+1];
  unsigned char w[_w_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (w, w_, _w_high+1);

  e = mcError_newWarning (mcLexBuf_getTokenNo ());
  e->s = doFormat1 ((const char *) a, _a_high, (const unsigned char *) w, _w_high);
}


/*
   flushErrors - switches the output channel to the error channel
                 and then writes out all errors.
*/

extern "C" void mcError_flushErrors (void)
{
  if (DebugTrace)
    {
      mcPrintf_printf0 ((const char *) "\\nFlushing all errors\\n", 23);
      mcPrintf_printf0 ((const char *) "===================\\n", 21);
    }
  if (flushAll (head, true))
    {
      M2RTS_ExitOnHalt (1);
      M2RTS_HALT (-1);
      __builtin_unreachable ();
    }
}


/*
   flushWarnings - switches the output channel to the error channel
                   and then writes out all warnings.
                   If an error is present the compilation is terminated,
                   if warnings only were emitted then compilation will
                   continue.
*/

extern "C" void mcError_flushWarnings (void)
{
  if (flushAll (head, false))
    {}  /* empty.  */
}


/*
   errorAbort0 - aborts compiling, it flushes all warnings and errors before aborting.
*/

extern "C" void mcError_errorAbort0 (const char *a_, unsigned int _a_high)
{
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  mcError_flushWarnings ();
  if (! (StrLib_StrEqual ((const char *) a, _a_high, (const char *) "", 0)))
    {
      mcError_writeFormat0 ((const char *) a, _a_high);
    }
  if (! (flushAll (head, true)))
    {
      mcError_writeFormat0 ((const char *) "unidentified error", 18);
      if (flushAll (head, true))
        {}  /* empty.  */
    }
  M2RTS_ExitOnHalt (1);
  M2RTS_HALT (-1);
  __builtin_unreachable ();
}

extern "C" void _M2_mcError_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
  init ();
}

extern "C" void _M2_mcError_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
